package ULHT.LIG2N1.RC.SERVER;

import ULHT.LIG2N1.RC.VO.BlacklistVO;
import ULHT.LIG2N1.RC.VO.QuestionVO;
import ULHT.LIG2N1.RC.VO.FileManage;
import ULHT.LIG2N1.RC.VO.QuestionLimitVO;
import ULHT.LIG2N1.RC.VO.QuestionListVO;
import ULHT.LIG2N1.RC.VO.WhitelistVO;
import java.util.*;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.joda.time.Period;
import org.joda.time.ReadablePartial;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

/**
 * Singleton com as variáveis de jogo. Todas as threads escrevem neste objecto
 *
 * @author Administrador
 */
public class GameVariables {

    // 
    private QuestionListVO questoes = new QuestionListVO();
    
    // fields
    private HashMap<String, ClientGameData> clients = new HashMap<>();
    private BlacklistVO blackList = new BlacklistVO();
    private WhitelistVO whiteList = new WhitelistVO();
    private int currentLevel = 1;
    private boolean playable;
    private DateTime horaInicioServidor = new DateTime();
    private DateTime horaInicioProximoJogo = new DateTime();
    private DateTime timeOutPerguntaActual = new DateTime();
    private int lastQuestionThrown = 0;
    private FileManage filemanager = new FileManage();
    private ArrayList<QuestionVO> gameQuestions;
    // constantes
    private static int LVL_ONE_REPLY_TIME = 15;
    private static int LVL_TWO_REPLY_TIME = 30;
    private static int LVL_THREE_REPLY_TIME = 45;
    private static int TOTAL_GAME_TIME = 600;
    private DateTimeFormatter fmt = DateTimeFormat.mediumTime();
    
    

    public GameVariables() {
        this.horaInicioServidor = DateTime.now();
        this.gameQuestions = questoes.getGameQuestions();
    }

    public GameVariables(HashMap<String, ClientGameData> clients, BlacklistVO blackList, WhitelistVO whiteList, int currentLevel, boolean playable) {
        this.clients = clients;
        this.blackList = blackList;
        this.whiteList = whiteList;
        this.currentLevel = currentLevel;
        this.playable = playable;
        this.horaInicioServidor = DateTime.now();
        this.gameQuestions = questoes.getGameQuestions();
    }

     /**
     * @return Retorna o score da questão 
     */
    public long getQuestionScore(int questionNumber) {
        return QuestionLimitVO.getquestionScore(questionNumber);
    }
    
 
    
    public int nextQuestionNumber() {
        lastQuestionThrown++;
        switch (lastQuestionThrown) {
            case 1:
                currentLevel = 1;
                break;
            case 5:
                currentLevel = 2;
                break;
            case 10:
                currentLevel = 3;
                break;
            case 15:
                currentLevel = 4;
                break;
        }
        return lastQuestionThrown;
    }

    public int getCurrentQuestionNumber(){
        return lastQuestionThrown;
    }
    
    public int getLastQuestionNumber() {
        return lastQuestionThrown;
    }

    public DateTime getTimeOutPerguntaActual() {
        return timeOutPerguntaActual;
    }

    public String getStringTimeOutPerguntaActual() {
        return timeOutPerguntaActual.toString(fmt.withLocale(Locale.FRANCE));
    }

    public void setTimeOutPerguntaActual(DateTime timeOutPerguntaActual) {
        this.timeOutPerguntaActual = timeOutPerguntaActual;
    }

    public void setPlayable(boolean playable) {
        this.playable = playable;
    }

    public boolean isPlayable() {
        return playable;
    }

    public DateTime getHoraInicioServidor() {
        return horaInicioServidor;
    }

    public String getStringHoraInicioServidor() {
        return horaInicioServidor.toString(fmt.withLocale(Locale.FRANCE));
    }

    public int getCurrentLevel() {
        return currentLevel;
    }

    public void setCurrentLevel(int currentLevel) {
        this.currentLevel = currentLevel;
    }

    public void setHoraInicioProximoJogo(DateTime horaInicioProximoJogo) {
        this.horaInicioProximoJogo = horaInicioProximoJogo;
    }

    public DateTime getHoraInicioProximoJogo() {
        return horaInicioProximoJogo;
    }

    public String getStringHoraInicioProximoJogo() {
        return horaInicioProximoJogo.toString(fmt.withLocale(Locale.FRANCE));
    }

    public String getStringTimeTillNextGame(){
        Period period = new Period(horaInicioProximoJogo, DateTime.now());
        return period.getMinutes() + ":" + period.getSeconds();
    }
    
    public HashMap<String, ClientGameData> getClients() {
        return clients;
    }

    public void addClient(ClientGameData clientGameData) {
        this.clients.put(clientGameData.getToken(), clientGameData);
    }

    public void setClients(HashMap<String, ClientGameData> clients) {
        this.clients = clients;
    }

    public Boolean isBlackedListed(String ipAddress) {
        //Iterar hashmap e verificar se o ipadress está na lista
        Iterator<ClientGameData> it = this.clients.values().iterator();
        while (it.hasNext()) {
            //Guarda Endereço IP para verificar
            ClientGameData clientGameData = it.next();

            //Obtem o ipAdress desta iteração
            String ipaddressIterado = clientGameData.getIpAdress().toString();

            //Verificar se o endereço existe na lista
            if (ipaddressIterado.equalsIgnoreCase(ipAddress)) {
                //Se existe vamos verificar se é Blacklisted
                if (clientGameData.isBlacklisted()) {
                    return true;
                } else {
                    return false;
                }
            }
        }
        //Se não existe na lista nenhum sai e retorna falso! 
        //Se não existe também não pode ser BlackListed
        return false;
    }

    /**
     * @return the gameQuestions
     */
    public ArrayList<QuestionVO> getGameQuestions() {
        return gameQuestions;
    }
    
    public boolean checkAnswer(int pergunta, String answer){
        return gameQuestions.get(pergunta - 1).getCerta().equalsIgnoreCase(answer);
    }

    public BlacklistVO getBlackList() {
        return blackList;
    }

    public WhitelistVO getWhiteList() {
        return whiteList;
    }
    
    public String getPlayersListStr(){
        String playersList = "";
        Iterator itr = clients.entrySet().iterator();
        
        while(itr.hasNext()){
            Map.Entry pares = (Map.Entry)itr.next();
            ClientGameData cli = (ClientGameData)pares.getValue();
            if (!cli.isBlacklisted() && !cli.isDisqualified())
                playersList += cli.getIpAdress() + "\n";
            
        }
        if (playersList.equals(""))
            playersList = "Nenhum jogador ligado!\n";
        return playersList;
    }
   
}
